﻿// MIT License
// 开源地址：https://gitee.com/co1024/AbcMvc
// Copyright (c) 2021-2022 1024
// Abc.Mvc=Furion+EF+SqlSugar+Pear layui admin.

namespace Abc.Core;
public static class SqlSugarDb
{
    /// <summary>
    /// 创建表
    /// </summary>
    /// <param name="databaseName"></param>
    /// <param name="databaseDirectory"></param>
    /// <param name="isInit">是否是初始化</param>
    public static void CreateTables(string databaseName = "", string databaseDirectory = "", bool isInit = false)
    {
        var sqlSugarDbSetting = SqlSugarCore.SqlSugarDbSetting;

        //判断是否是初始化且启用了初始化数据库
        if (sqlSugarDbSetting.EnableInitDatabase == false && isInit == true) return;

        //创建数据库
        var _db = SqlSugarHelper.Db;
        foreach (var conn in sqlSugarDbSetting.ConnectionConfigs)
        {
            if (conn.DbType != DbType.Oracle)
                _db.DbMaintenance.CreateDatabase();
        }

        ////判断传入的数据库名是否为空，如果为空则使用配置文件的名称
        //if (string.IsNullOrWhiteSpace(databaseName))
        //{
        //    databaseName = sqlSugarDbSetting.DataBaseName;
        //}
        ////判断传入的数据库目录是否为空，如果为空则使用配置文件的目录
        //if (string.IsNullOrWhiteSpace(databaseDirectory))
        //{
        //    databaseDirectory = sqlSugarDbSetting.DatabaseDirectory;
        //}

        //获取所有实体的 Type
        var entityTypes = GetAllEntitiesTypes();
        ////创建表、迁移表
        //SqlSugarDbContext.Db.ScopedContext.CodeFirst.InitTables(alltypes.ToArray());//根据types创建表
        foreach (var entityType in entityTypes)
        {
            var tAtt = entityType.GetCustomAttribute<TenantAttribute>();
            var configId = tAtt?.configId.ToString() ?? "";
            if (configId == null || string.IsNullOrWhiteSpace(configId))
            {
                configId = sqlSugarDbSetting.ConnectionConfigs.FirstOrDefault()?.ConfigId;
            }
            if (string.IsNullOrWhiteSpace(configId))
            {
                configId = SqlSugarConst.ConfigId;
            }
            //var provider = _db.GetConnectionScope(tAtt == null ? SqlSugarConst.ConfigId : tAtt.configId);
            var provider = _db.GetConnectionScope(configId);
            //provider.CodeFirst.SetStringDefaultLength(0);//设置字符串默认长度
            provider.CodeFirst.SetStringDefaultLength(500).InitTables(entityType);
        }
    }

    /// <summary>
    /// 初始化数据种子
    /// </summary>
    public static void InitDataSeed(bool isInit = false)
    {
        var sqlSugarDbSetting = SqlSugarCore.SqlSugarDbSetting;
        //判断是否是初始化且启用了初始化数据库
        if (sqlSugarDbSetting.EnableInitDatabase == false && isInit == true) return;

        var db = SqlSugarHelper.Db;
        // 获取所有实体种子数据
        var seedDataTypes = App.EffectiveTypes.Where(u => !u.IsInterface && !u.IsAbstract && u.IsClass
            && u.GetInterfaces().Any(i => i.HasImplementedRawGeneric(typeof(ISqlSugarEntitySeedData<>))));
        if (!seedDataTypes.Any()) return;

        //循环处理数据种子
        foreach (var seedType in seedDataTypes)
        {
            var instance = Activator.CreateInstance(seedType);
            //获取数据种子的方法
            var hasDataMethod = seedType.GetMethod("HasData", genericParameterCount: 0, new Type[] { });
            //获取数据种子的数据
            var seedData = ((IEnumerable)hasDataMethod?.Invoke(instance, null))?.Cast<object>();
            if (seedData == null) continue;

            var entityType = seedType.GetInterfaces().First().GetGenericArguments().First();
            var tAtt = entityType.GetCustomAttribute<TenantAttribute>();
            //配置ID
            var configId = tAtt?.configId.ToString() ?? "";
            if (configId == null || string.IsNullOrWhiteSpace(configId))
            {
                configId = sqlSugarDbSetting.ConnectionConfigs.FirstOrDefault()?.ConfigId;
            }
            if (string.IsNullOrWhiteSpace(configId))
            {
                configId = SqlSugarConst.ConfigId;
            }

            //var provider = db.GetConnectionScope(tAtt == null ? SqlSugarConst.ConfigId : tAtt?.configId);
            //获取指定配置的连接
            var provider = db.GetConnectionScope(configId);

            var seedDataTable = seedData.ToList().ToDataTable();
            seedDataTable.TableName = db.EntityMaintenance.GetEntityInfo(entityType).DbTableName;
            if (seedDataTable.Columns.Contains(SqlSugarConst.PrimaryKey))
            {
                var storage = provider.Storageable(seedDataTable).WhereColumns(SqlSugarConst.PrimaryKey).ToStorage();
                // 如果添加一条种子数，sqlsugar 默认以 @param 的方式赋值，如果 PropertyType 为空，则默认数据类型为字符串。插入 pgsql 时候会报错，所以要忽略为空的值添加

                var isSingle = ((InsertableProvider<Dictionary<string, object>>)storage.AsInsertable).IsSingle;
                if (isSingle)
                {
                    //var sql = storage.AsInsertable.IgnoreColumns("Id", "UpdateTime", "UpdateUserId", "CreatorUserId").ToSqlString();
                    storage.AsInsertable.ExecuteCommand();
                }
                else
                {
                    var a = storage.AsInsertable.ToSqlString();
                    storage.AsInsertable.ExecuteCommand();
                }
                //_ = ((InsertableProvider<Dictionary<string, object>>)storage.AsInsertable).IsSingle ?
                //    storage.AsInsertable.IgnoreColumns("UpdateTime", "UpdateUserId", "CreatorUserId", "Id").ExecuteCommand() :
                //    storage.AsInsertable.IgnoreColumns("Id").ExecuteCommand();
                storage.AsUpdateable.ExecuteCommand();
            }
            else // 没有主键或者不是预定义的主键(没主键有重复的可能)
            {
                var storage = provider.Storageable(seedDataTable).ToStorage();
                storage.AsInsertable.ExecuteCommand();
            }
        }
    }

    /// <summary>
    /// 数据库表 结构对比
    /// </summary>
    /// <returns>返回表结构对比结果</returns>
    public static string DifferenceTables()
    {
        //获取所有实体的 Type
        var alltypes = GetAllEntitiesTypes();
        //对比表
        var diffString = SqlSugarHelper.Db.CodeFirst.GetDifferenceTables(alltypes.ToArray()).ToDiffString();
        //返回表的对比结果
        return diffString;
    }


    /// <summary>
    /// 获取所有实体的 Type
    /// </summary>
    /// <param name="isCompatibleEF">是否兼容EF</param>
    /// <returns></returns>
    public static Type[] GetAllEntitiesTypes(bool isCompatibleEF = true)
    {
        if (isCompatibleEF)
        {
            var types = App.EffectiveTypes.Where(u =>
                !u.IsInterface
                && !u.IsAbstract
                && u.IsClass
                && (u.IsDefined(typeof(SugarTable), false) || u.IsDefined(typeof(TableAttribute), false))
                && !u.IsDefined(typeof(NotTableAttribute), false)
               ).ToArray();

            return types;
        }
        else
        {
            var types = App.EffectiveTypes.Where(u =>
                !u.IsInterface
                && !u.IsAbstract
                && u.IsClass
                && u.IsDefined(typeof(SugarTable), false)
                && !u.IsDefined(typeof(NotTableAttribute), false)
               ).ToArray();

            return types;
        }

    }


}
